package com.cy.teducommunitys.com.cy.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cy.teducommunitys.com.cy.entity.Authority;
import com.cy.teducommunitys.com.cy.entity.Menu;
import com.cy.teducommunitys.com.cy.entity.User;
import com.cy.teducommunitys.com.cy.mapper.AuthorityMapper;
import com.cy.teducommunitys.com.cy.mapper.MenuMapper;
import com.cy.teducommunitys.com.cy.mapper.UserMapper;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
public class ShiroUserRealm extends AuthorizingRealm {
    @Autowired
    private AuthorityMapper authorityMapper;
    @Autowired
    private MenuMapper menuMapper;
    @Autowired
    private UserMapper userMapper;
    /**
     * 设置凭证匹配器(与用户添加操作使用相同的加密算法)
     */
    @Override
    public void setCredentialsMatcher(
            CredentialsMatcher credentialsMatcher) {
        //构建凭证匹配对象
        HashedCredentialsMatcher cMatcher =
                new HashedCredentialsMatcher();
        //设置加密算法
        cMatcher.setHashAlgorithmName("MD5");
        //设置加密次数
        cMatcher.setHashIterations(1);
        super.setCredentialsMatcher(cMatcher);
    }

    /**
     * 通过此方法完成认证数据的获取及封装,系统
     * 底层会将认证数据传递认证管理器，由认证
     * 管理器完成认证操作。
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token)
            throws AuthenticationException {
        //1.获取用户名(用户页面输入)
        UsernamePasswordToken upToken =
                (UsernamePasswordToken) token;
        String username = upToken.getUsername();
        //2.基于用户名查询用户信息
        User user =
                userMapper.selectOne(new QueryWrapper<User>().eq("userName",username));
        //3.判定用户是否存在
        if (user == null)
            throw new UnknownAccountException();
        //4.判定用户是否已被禁用。
        if (user.getValid() == 0)
            throw new LockedAccountException();

        //5.封装用户信息
        ByteSource credentialsSalt =
                ByteSource.Util.bytes(user.getSalt());
        //记住：构建什么对象要看方法的返回值
        SimpleAuthenticationInfo info =
                new SimpleAuthenticationInfo(
                        user,//principal (身份)
                        user.getPassword(),//hashedCredentials
                        credentialsSalt, //credentialsSalt
                        getName());//realName
        //6.返回封装结果
        return info;//返回值会传递给认证管理器(后续
        //认证管理器会通过此信息完成认证操作)
    }

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals){
        //1.获取登录用户信息,例如用户id
    User user = (User) principals.getPrimaryPrincipal();
    //2.基于角色id获取菜单id
    Integer roleId = user.getRoleId();
    List<Authority> authorityList = authorityMapper.selectList(new QueryWrapper<Authority>().eq("roleIed", roleId));
    if (authorityList==null||authorityList.size()==0)throw new AuthorizationException ();
        //3.基于菜单id获取权限标识
    Set<String> set = new HashSet<>();
    for (Authority a:authorityList){
        Menu menu = menuMapper.selectOne(new QueryWrapper<Menu>().eq("menuId", a.getMenuId()));
        //4.对权限标识信息进行封装并返回
        String permission = menu.getPermission();
        if (!StringUtils.isEmpty(permission)){
            set.add(permission);
        }
    }
//    List<String> permissions = MenuMapper.findPermissions(menuIds.toArray(array));
//
//    for (String per:permissions){
//        if (!StringUtils.isEmpty(per)){
//            set.add(per);
//        }
//    }
    SimpleAuthorizationInfo info=
            new SimpleAuthorizationInfo();
    info.setStringPermissions(set);
    return info;//返回给授权管理器

}


}